🎖️GitЯра🎖️
Reticulum Relay Chat (RRC) implementation reference with extensions
>rrcd
T383838rrcd is a standalone RRC hub daemon (server) built on Reticulum (RNS).
• License: MIT (see LICENSE)
• Changelog: CHANGELOG.md
• Versioning policy: VERSIONING.md
Install (dev)
From the T383838rrcd/ directory:
To install from source (non-editable):
• T383838python -m pip install .
• T383838python -m pip install -e .
For contributors (lint + tests):
• T383838python -m pip install -e ".[dev]"
• T383838ruff check .
• T383838pytest -q
Run
To run a basic RRC hub with default settings:
• T383838rrcd
You can also run it as a module:
• T383838python -m rrcd
First run will create a default config file at T383838~/.rrcd/rrcd.toml and
a default identity at T383838~/.rrcd/hub_identity, plus a room registry at
T383838~/.rrcd/rooms.toml. You should read and edit the config before starting again.
To override the default state directory (T383838~/.rrcd/), set T383838RRCD_HOME, e.g.
T383838RRCD_HOME=/tmp/rrcd rrcd.
To specify a custom identity path:
• T383838rrcd --identity ~/.rrcd/hub_identity
The hub destination namespace is fixed at T383838rrc.hub so clients can discover
hubs consistently.
Optional:
• T383838rrcd --config rrcd.toml
You need a working Reticulum configuration (see Reticulum docs).
Logging
By default, T383838rrcd logs to stderr (good for systemd/journald). You can configure
logging in T383838~/.rrcd/rrcd.toml:
T282828
Tff7b72[Tff7b72loggingTff7b72]
Te6edf3level Tff7b72= Ta5d6ff"Ta5d6ffINFOTa5d6ff" T8b949e# set to DEBUG for connection/packet tracing
Te6edf3rns_level Tff7b72= Ta5d6ff"Ta5d6ffWARNINGTa5d6ff" T8b949e# python-logging level for the "RNS" logger (if used)
Te6edf3console Tff7b72= Tff7b72true
Te6edf3file Tff7b72= Ta5d6ff"Ta5d6ff" T8b949e# e.g. "~/.rrcd/rrcd.log" (empty disables)
Te6edf3format Tff7b72= Ta5d6ff"Ta5d6ff%(asctime)s %(levelname)s %(name)s[%(threadName)s]: %(message)sTa5d6ff"
Te6edf3datefmt Tff7b72= Ta5d6ff"Ta5d6ff"
CLI overrides are also available:
• T383838rrcd --log-level DEBUG
• T383838rrcd --log-file ~/.rrcd/rrcd.log
If you use T383838/reload, logging settings are applied immediately.
Troubleshooting: connect times out after HELLO
If a client connects, sends T383838HELLO, and then times out waiting for T383838WELCOME,
check the hub logs for an error like:
• T383838Packet size of ... exceeds MTU of ... bytes
This usually means the hub tried to send a T383838WELCOME (or other message) that is
too large for the current Reticulum link MTU.
Mitigations:
• T383838WELCOME sent by T383838rrcd is intentionally minimal (hub name/version/caps).
• The hub T383838greeting is delivered after T383838WELCOME via one or more T383838NOTICE
messages chunked to fit the link MTU.
Compatibility
T383838rrcd implements the core RRC protocol as described in the RRC docs.
Protocol alignment notes (for implementers):
• T383838HELLO and T383838WELCOME bodies are CBOR maps with unsigned integer keys.
• Capabilities are carried in body key T3838382 as a CBOR map (not a bitmask). Keys
inside the capabilities map are unsigned integers; values are advisory.
• Core room content types include T383838MSG, T383838NOTICE, and T383838ACTION (type T38383822).
• T383838WELCOME is intentionally minimal (hub name/version/caps only). Any hub
greeting text is delivered after T383838WELCOME via one or more T383838NOTICE messages.
Extensions beyond core RRC will be documented in the Extensions section of this
README as they are added.
In addition to the core protocol, T383838rrcd includes operator-facing and
policy-level features that are allowed by the spec:
• First-run bootstrap: if the default config and identity are missing,
T383838rrcd will create them and exit with a note asking you to edit the config
before starting again.
• Rate limiting: per-link message rate limiting may reject messages with
T383838ERROR.
• Room and input limits: limits such as maximum rooms per session and
maximum room name length.
• Optional T383838JOINED member list: can include a best-effort list of members.
• Optional hub-initiated T383838PING: can periodically ping clients and
optionally close links that do not respond in time.
Extensions
Suggested reading: EX1-RRCD.md
T383838rrcd intentionally avoids adding new on-wire message types. Operator features
use a hub-local convention: if a client sends a T383838MSG/T383838NOTICE whose body is a
string beginning with T383838/, and the command is recognized, the hub treats it as a
command and does not forward it.
T383838ACTION is treated as normal room content and is forwarded unchanged. T383838rrcd
does not interpret T383838ACTION bodies as slash commands.
Wire-level extensions (backwards-compatible):
• Optional envelope nickname: the hub may include an additional envelope key
T383838K_NICK = 7 (string) when forwarding T383838MSG/T383838NOTICE. This is an optional
hint associated with T383838K_SRC so clients can display a human-friendly
nickname instead of only the sender identity hash.
The hub learns this value from the client's optional envelope nickname field
T383838K_NICK = 7 on inbound messages, and treats it as the authoritative nickname
for that link. Clients should treat T383838K_NICK as optional and fall back to
T383838K_SRC when it is missing.
Nicknames are advisory only; clients should treat them as display hints.
The hub may ignore, sanitize, replace, or omit them.
Current hub sanitation policy: store/emit only trimmed nicknames that are
UTF-8 encodable, contain no newlines/NUL, and are at most T383838nick_max_chars
characters (default: 32).
• Direct NOTICE destination: the hub supports client-to-client T383838NOTICE
delivery using an optional envelope key T383838K_DST = 8 (bytes), containing the
full destination identity hash.
This extension applies only to T383838NOTICE. When T383838K_DST is present, the hub
delivers the message to exactly one connected client identified by that full
hash instead of broadcasting by room membership. The forwarded T383838NOTICE
preserves T383838K_DST so the recipient can distinguish direct delivery from
room traffic without out-of-band state.
Direct T383838NOTICE messages must not also include T383838K_ROOM. Mixed room and
direct-destination semantics are rejected with T383838ERROR.
Support for this extension is advertised in T383838WELCOME capabilities via
T383838CAP_DIRECT_NOTICE = 2. Clients should only send T383838K_DST-addressed notices
after confirming hub support.
• Large payload transfer via RNS.Resource: For messages that exceed the link
MTU (Maximum Data Unit), T383838rrcd can automatically use RNS.Resource for
reliable large payload transfer instead of manual chunking.
This is implemented as a two-part protocol:
1. Send a small T383838RESOURCE_ENVELOPE message (type 50) via normal packet,
announcing the incoming resource with metadata (id, kind, size, SHA256).
2. Send the actual payload via T383838RNS.Resource.
The receiving side matches the resource to the expectation and validates
integrity. Supported resource kinds include:
• T383838notice: Large NOTICE text messages
• T383838motd: Message of the day / server greeting
• T383838blob: Generic binary data
Configuration (in T383838rrcd.toml):
T282828
Tff7b72[Tff7b72hubTff7b72]
Te6edf3enable_resource_transfer Tff7b72= Tff7b72true T8b949e# default: true
Te6edf3max_resource_bytes Tff7b72= T79c0ff262144 T8b949e# 256 KiB default
Te6edf3max_pending_resource_expectations Tff7b72= T79c0ff8 T8b949e# per link
Te6edf3resource_expectation_ttl_s Tff7b72= T79c0ff30.0 T8b949e# expectation timeout
Safety controls:
• Resources are only accepted if they match a recent expectation
• Size limits enforced (default 256 KiB)
• SHA256 verification for integrity
• TTL-based expectation expiry (default 30 seconds)
• Per-link expectation limit to prevent memory exhaustion
Fallback: If resource transfer is disabled or fails, NOTICE messages fall
back to the original line-based chunking method.
Configure trusted operators and banned identities in the TOML config:
• T383838trusted_identities: list of Reticulum Identity hashes (hex) allowed to run
commands
• T383838banned_identities: list of Identity hashes (hex) that are disconnected on
identify
Implemented commands (best-effort):
Server operator commands (require identity in T383838trusted_identities):
• T383838/stats — show hub stats (uptime, clients, rooms, counters)
• T383838/reload — reload T383838rrcd.toml and T383838rooms.toml from disk
• T383838/who [room] — list members (nick and/or hash prefix); private rooms (T383838+p)
are hidden from non-operators
• T383838/kline add <nick|hashprefix|hash> — add a server-global ban (persists to
T383838banned_identities)
• T383838/kline del <hash> — remove a server-global ban (persists to
T383838banned_identities)
• T383838/kline list — list global bans
Room moderation commands (room founder/ops; some actions may also work for
server operators):
• T383838/kick <room> <nick|hashprefix> — remove a client from a room
• T383838/register <room> — persist room settings to T383838rooms.toml (founder only; must
be in the room)
• T383838/unregister <room> — remove room settings from T383838rooms.toml (founder only;
must be in the room)
• T383838/topic <room> [topic] — show or set a room topic
• T383838/mode <room> (+m|-m) — set moderated mode
• T383838/mode <room> (+i|-i) — set invite-only mode
• T383838/mode <room> (+k|-k) [key] — set/clear room key (password)
• T383838/mode <room> (+p|-p) — set/clear private mode (room hidden from T383838/list and
T383838/who for non-operators)
• T383838/mode <room> (+t|-t) — set topic-ops-only (only ops can change topic)
• T383838/mode <room> (+n|-n) — set no-outside-messages
• T383838/mode <room> (+r|-r) — read-only; use /register or /unregister
• T383838/mode <room> (+o|-o|+v|-v) <nick|hashprefix|hash> — IRC-style user modes
(alias for op/voice)
• T383838/op <room> <nick|hashprefix|hash> / T383838/deop ... — grant/revoke room operator
• T383838/voice <room> <nick|hashprefix|hash> / T383838/devoice ... — grant/revoke voice
(for moderated rooms)
• T383838/ban <room> add <nick|hashprefix|hash> — add a room-local ban
• T383838/ban <room> del <nick|hashprefix|hash> — remove a room-local ban
• T383838/ban <room> list — list room-local bans
• T383838/invite <room> add <nick|hashprefix|hash> — send a room invite (as a
T383838NOTICE to the target)
• T383838/invite <room> del <nick|hashprefix|hash> — remove a room-local invite
• T383838/invite <room> list — list room-local invites
• T383838/list — list all registered public rooms with their topics
Notes:
• On successful JOIN, the hub sends a follow-up T383838NOTICE to the joining client
with room info (registered/unregistered, mode flags, and topic).
• When a room is registered, default mode flags are T383838+nrt.
• T383838/invite always sends the target a T383838NOTICE (and fails if the target is not
currently connected).
• If the room has join restrictions, the hub also records an expiring invite so
the target can actually use it to join:
• T383838+i (invite-only): only an invite allows a user to JOIN.
• T383838+k (keyed): an invite allows a user to JOIN without knowing the key. The
key can then be disseminated in-band (in room) if desired.
These stored invites are consumed on successful JOIN or discarded when they
expire. Configure the expiry with T383838room_invite_timeout_s in T383838rrcd.toml.
• Registered-but-empty rooms may be pruned after a period of inactivity.
Configure T383838room_registry_prune_after_s and T383838room_registry_prune_interval_s
in T383838rrcd.toml.
rooms.toml format
The room registry file (T383838~/.rrcd/rooms.toml by default) is a TOML document with
a top-level T383838[rooms] table. Each registered room is stored under a per-room
table.
Example:
• T383838[rooms."lobby"]
Supported keys per room:
• T383838founder: hex Reticulum Identity hash (string)
• T383838topic: room topic (string, optional)
• T383838moderated: whether the room is in +m (bool)
• T383838invite_only: whether the room is in +i (bool)
• T383838topic_ops_only: whether the room is in +t (bool)
• T383838no_outside_msgs: whether the room is in +n (bool)
• T383838private: whether the room is in +p (bool; room hidden from T383838/list)
• T383838key: room key/password for +k (string, optional)
• T383838operators: list of identity hashes (strings)
• T383838voiced: list of identity hashes (strings)
• T383838bans: list of identity hashes (strings)
• T383838invited: table mapping identity hash (hex string) -> expiry unix timestamp
seconds (float)
• T383838last_used_ts: unix timestamp seconds (float; used for pruning)
Note: room names are TOML keys. Quote room names that contain spaces or other
non-identifier characters, e.g. T383838[rooms."my room"].
Security and threat model
This section describes what T383838rrcd is designed to protect against, what it is
not designed to protect against, and the assumptions you should keep in mind
when deploying it.
Assumptions:
• Reticulum link establishment and remote identity are authoritative for who a
peer “is” (the hub uses the Link’s remote identity hash as the peer
identity).
• The host running T383838rrcd is trusted by the operator (if the host is
compromised, the hub and its policy controls are compromised).
What T383838rrcd aims to protect against:
• Unauthenticated pre-handshake traffic: inbound packets are ignored until
the Link’s remote identity is available.
• Protocol misuse: clients must T383838HELLO before they can perform other
actions (WELCOME gating).
• Accidental resource exhaustion: basic per-link rate limiting and input
limits (rooms per session, room name length).
• Basic abuse controls: operator identities, global bans (T383838/kline), and
per-room bans/modes.
What T383838rrcd does not protect against (non-goals):
• Denial of service by a determined attacker: rate limiting is best-effort
and does not prevent all forms of DoS.
• A malicious or compromised operator: identities in T383838trusted_identities
can enforce policy; they can also abuse that power.
• Metadata/privacy leakage outside the hub’s control: your threat model
depends on Reticulum’s transport and your network topology.
• Confidentiality against the hub itself: the hub can observe and forward
traffic; do not treat it as a “zero trust” component.
Operational guidance:
• Keep the hub identity file and config directory private (the default storage
directory is T383838~/.rrcd/).
• Treat T383838trusted_identities like admin keys.
• Prefer running T383838rrcd under a dedicated OS user with locked-down permissions,
aka “least privilege” principle. TL;DR: don’t run it as root.
Served by rngit 1.4.2 - Generated in 0.1s